#include <prism/frontend/semantic_analysis/resolve/identifier.hpp>
//=====================================================================
#include <prism/frontend/syntactical_analysis/marshall.hpp>


//=====================================================================
// identifier_matches_pred
//=====================================================================
prism::resolve::identifier_matches_pred::identifier_matches_pred( sooty::const_parseme_ptr_ref caller )
	: caller(caller)
{
	ATMA_ASSERT(caller->id == ID::identifier);
}

bool prism::resolve::identifier_matches_pred::operator()( sooty::const_parseme_ptr_ref candidate ) const
{
	return candidate->id == ID::variable_definition
		&& marshall::variable_definition::name(candidate)->value.string == caller->value.string;
}



sooty::parseme_ptr prism::resolve::identifier_to_variable_definition(sooty::const_parseme_ptr_ref N)
{
	ATMA_ASSERT(N && N->id == ID::identifier);

	// find our enclosing function
	sooty::parseme_ptr function = sooty::direct_upwards_find_first_if(N, detail::is_function);

	// currently, we don't have variable definitions outside of functions.
	// at some point in the future, we'll have them as members of types, but until then...
	if (!function) return sooty::parseme_ptr();

	// from the function-body, mabye find an identifier!
	sooty::parseme_ptr local_vd = sooty::depth_first_find_first_if( marshall::function::body(function), identifier_matches_pred(N), false );
	if (local_vd) return local_vd;

	// if we can't find an identifier, do the same thing for our parameters
	sooty::parseme_ptr param_vd = sooty::depth_first_find_first_if( marshall::function::parameter_list(function), identifier_matches_pred(N), false );
	if (param_vd) return param_vd;

	// :(
	return sooty::parseme_ptr();
}